#pragma once
#include <iostream>
#include <memory>
#include <functional>
#include <sys/wait.h>
#include "Socket.h"

namespace TcpServeMoule
{
    using namespace LogMudule;
    using namespace sockedmodule;
    using tcphander_t = std::function<bool(SockPtr, IntAddr)>;
    class TcpServe
    {
    public:
        TcpServe(int port)
            : _listensocket(std::make_unique<TcpSocket>()), _running(false), _port(port)
        {
        }
        void Init(tcphander_t handler)
        {
            _handler = handler;
            _listensocket->BuildTcpSocketMethod(_port);
        }
        void Loop()
        {
            _running = true;
            while (1)
            {
                IntAddr clientaddr;
                auto socket = _listensocket->Accepter(&clientaddr);
                if (socket == nullptr)
                {
                    continue;
                }
                LOG(LogLevel::INFO) << "get new socket is " << clientaddr.Addr();

                pid_t id = fork();
                if (id == 0)
                {
                    _listensocket->Close();
                    if (fork() > 0)
                    {
                        exit(1);
                    }
                    _handler(socket, clientaddr);
                    exit(0);
                }
                socket->Close();
                waitpid(id, nullptr, 0);
            }
            _running = false;
        }
        ~TcpServe()
        {
            _listensocket->Close();
        }

    private:
        std::unique_ptr<Socket> _listensocket;
        bool _running;
        tcphander_t _handler;
        int _port;
    };
}
